package com.example.common.unit;

import com.example.module.goods.DO.GoodsAddDO;
import com.example.module.shoppingCart.DO.CartUpdateDO;
import com.example.module.shoppingCart.DO.ShoppingCartAddDO;
import com.example.module.user.DO.UserRegisterDO;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author ghy
 * @date 2025/08/06
 * @description 通用的Form转DO工具类
 */
@Component
public class ConvertUnit {
    /**
     * 将 Form对象转换为 DO对象
     * 通过反射机制，将Form中同名的属性值复制到DO对象中
     *
     * @param form    Form对象
     * @param doClass DO类的Class对象
     * @param <T>     DO对象类型
     * @return 转换后的DO对象
     * @throws RuntimeException 转换过程中出现的异常
     */
    public static <T> T FormToDO(Object form, Class<T> doClass) {
        try {
            // 创建 DO对象实例
            T doInstance = doClass.getDeclaredConstructor().newInstance();
            // 获取Form对象的所有字段
            Field[] formFields = getAllFields(form.getClass());
            // 遍历 Form对象的字段
            for (Field formField : formFields) {
                formField.setAccessible(true);
                String fieldName = formField.getName();
                // 获取字段值
                Object fieldValue = formField.get(form);
                // 在 DO对象中查找对应的 setter方法
                try {
                    String setterName = "set" + capitalize(fieldName);
                    Class<?> fieldType = formField.getType();
                    Method setterMethod = doClass.getMethod(setterName, fieldType);
                    setterMethod.invoke(doInstance, fieldValue);
                } catch (NoSuchMethodException e) {
                    // 如果DO中没有对应的setter方法，则跳过
                    continue;
                }
            }
            // 特殊处理 1：如果目标对象是UserRegisterDO，设置注册时间
            if (doInstance instanceof UserRegisterDO) {
                ((UserRegisterDO) doInstance).setUserRegisterTime(new Date());
            }
            // 特殊处理 2：如果目标对象是GoodsAddDO，设置商品上架时间
            if (doInstance instanceof GoodsAddDO) {
                ((GoodsAddDO) doInstance).setGoodsUptime(new Date());
            }
            // 特殊处理 3：如果目标对象是ShoppingCartAddDO，设置加入购物车的时间
            if (doInstance instanceof ShoppingCartAddDO) {
                ((ShoppingCartAddDO) doInstance).setShoppingAddTime(new Date());
            }
            // 特殊处理 4：如果目标对象是CartUpdateDO，设置加入购物车更新时间
            if (doInstance instanceof CartUpdateDO) {
                ((CartUpdateDO) doInstance).setShoppingUpdateTime(new Date());
            }
            return doInstance;
        } catch (Exception e) {
            throw new RuntimeException("Form转DO转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 将DO对象转换为另一个DO对象
     * 通过反射机制，将源DO中同名的属性值复制到目标DO对象中
     *
     * @param source      源DO对象
     * @param targetClass 目标DO类的Class对象
     * @param <T>         目标DO对象类型
     * @return 转换后的DO对象
     * @throws RuntimeException 转换过程中出现的异常
     */
    public static <T> T DOToDO(Object source, Class<T> targetClass) {
        try {
            // 创建目标DO对象实例
            T targetInstance = targetClass.getDeclaredConstructor().newInstance();
            // 获取源对象的所有字段
            Field[] sourceFields = getAllFields(source.getClass());
            // 遍历源对象的字段
            for (Field sourceField : sourceFields) {
                sourceField.setAccessible(true);
                String fieldName = sourceField.getName();
                // 获取字段值
                Object fieldValue = sourceField.get(source);
                // 在目标对象中查找对应的setter方法
                try {
                    String setterName = "set" + capitalize(fieldName);
                    Class<?> fieldType = sourceField.getType();
                    Method setterMethod = targetClass.getMethod(setterName, fieldType);
                    setterMethod.invoke(targetInstance, fieldValue);
                } catch (NoSuchMethodException e) {
                    // 如果目标DO中没有对应的setter方法，则跳过
                    continue;
                }
            }
            return targetInstance;
        } catch (Exception e) {
            throw new RuntimeException("DO转DO转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 将 Form对象转换为 BO对象
     * 通过反射机制，将Form中同名的属性值复制到BO对象中
     *
     * @param form    Form对象
     * @param boClass BO类的Class对象
     * @param <T>     BO对象类型
     * @return 转换后的BO对象
     * @throws RuntimeException 转换过程中出现的异常
     */
    public static <T> T FormToBO(Object form, Class<T> boClass) {
        try {
            // 创建 BO对象实例
            T boInstance = boClass.getDeclaredConstructor().newInstance();
            // 获取Form对象的所有字段
            Field[] formFields = getAllFields(form.getClass());
            // 遍历 Form对象的字段
            for (Field formField : formFields) {
                formField.setAccessible(true);
                String fieldName = formField.getName();
                // 获取字段值
                Object fieldValue = formField.get(form);
                // 在 BO对象中查找对应的 setter方法
                try {
                    String setterName = "set" + capitalize(fieldName);
                    Class<?> fieldType = formField.getType();
                    Method setterMethod = boClass.getMethod(setterName, fieldType);
                    setterMethod.invoke(boInstance, fieldValue);
                } catch (NoSuchMethodException e) {
                    // 如果BO中没有对应的setter方法，则跳过
                    continue;
                }
            }
            return boInstance;
        } catch (Exception e) {
            throw new RuntimeException("Form转BO转换失败: " + e.getMessage(), e);
        }
    }


    /**
     * 将DO对象转换为VO对象
     * 通过反射机制，将DO中同名的属性值复制到VO对象中
     * 特殊处理userSex字段：0对应女，1对应男，2对应未知
     *
     * @param source      源DO对象
     * @param targetClass 目标VO类的Class对象
     * @param <T>         目标VO对象类型
     * @return 转换后的VO对象
     * @throws RuntimeException 转换过程中出现的异常
     */
    public static <T> T DOToVO(Object source, Class<T> targetClass) {
        try {
            // 创建目标VO对象实例
            T targetInstance = targetClass.getDeclaredConstructor().newInstance();
            // 获取源对象的所有字段
            Field[] sourceFields = getAllFields(source.getClass());
            // 遍历源对象的字段
            for (Field sourceField : sourceFields) {
                sourceField.setAccessible(true);
                String fieldName = sourceField.getName();
                // 获取字段值
                Object fieldValue = sourceField.get(source);
                // 特殊处理userSex字段
                if ("userSex".equals(fieldName) && fieldValue instanceof Integer) {
                    Integer sexValue = (Integer) fieldValue;
                    switch (sexValue) {
                        case 0:
                            fieldValue = "女";
                            break;
                        case 1:
                            fieldValue = "男";
                            break;
                        case 2:
                            fieldValue = "保密";
                            break;
                        default:
                            fieldValue = "未知";
                            break;
                    }
                    // 查找VO中的userSex字段并设置值
                    try {
                        String setterName = "set" + capitalize(fieldName);
                        Method setterMethod = targetClass.getMethod(setterName, String.class);
                        setterMethod.invoke(targetInstance, fieldValue);
                    } catch (NoSuchMethodException e) {
                        // 如果VO中没有对应的setter方法，则跳过
                        continue;
                    }
                    continue;
                }
                // 在目标对象中查找对应的setter方法
                try {
                    String setterName = "set" + capitalize(fieldName);
                    Class<?> fieldType = sourceField.getType();
                    Method setterMethod = targetClass.getMethod(setterName, fieldType);
                    setterMethod.invoke(targetInstance, fieldValue);
                } catch (NoSuchMethodException e) {
                    // 如果目标VO中没有对应的setter方法，则跳过
                    continue;
                }
            }
            return targetInstance;
        } catch (Exception e) {
            throw new RuntimeException("DO转VO转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取类及其父类的所有字段
     *
     * @param clazz 类对象
     * @return 所有字段数组
     */
    private static Field[] getAllFields(Class<?> clazz) {
        // 获取当前类声明的字段
        Field[] declaredFields = clazz.getDeclaredFields();
        // 获取父类
        Class<?> superclass = clazz.getSuperclass();
        // 如果父类不是Object类，则递归获取父类字 段
        if (superclass != null && superclass != Object.class) {
            Field[] parentFields = getAllFields(superclass);
            Field[] allFields = new Field[declaredFields.length + parentFields.length];
            System.arraycopy(declaredFields, 0, allFields, 0, declaredFields.length);
            System.arraycopy(parentFields, 0, allFields, declaredFields.length, parentFields.length);
            return allFields;
        }
        return declaredFields;
    }

    /**
     * 首字母大写
     *
     * @param str 字符串
     * @return 首字母大写的字符串
     */
    private static String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
}
